﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;

using LuaInterface;

namespace Codeology.Auctioneer
{

    public class AuctioneerItem
    {

        private string link;
        private int item_level;
        private string type;
        private string sub_type;
        private AuctioneerEquipmentSlot equip_slot;
        private AuctioneerMoney price;
        private AuctioneerTimeLeft time_left;
        private DateTime time;
        private string name;
        private string texture;
        private int count;
        private AuctioneerItemQuality quality;
        private int can_use;
        private int usable_level;
        private AuctioneerMoney min_bid;
        private AuctioneerMoney min_inc;
        private AuctioneerMoney buy_out;
        private AuctioneerMoney cur_bid;
        private bool am_high;
        private string seller;
        private AuctioneerItemFlag flag;
        private int auctioneer_id;
        private int item_id;
        private int suffix;
        private int factor;
        private int enchant;
        private long seed;

        internal AuctioneerItem(LuaTable table)
        {
            // Create somewhere to put item parts
            Dictionary<int,string> parts = new Dictionary<int,string>();

            // Process item into parts
            foreach(DictionaryEntry entry in table) {
                // Get Key
                int key = int.Parse(entry.Key.ToString());

                // Get Value
                string value = entry.Value.ToString();

                // Add to parts
                parts.Add(key,value);
            }

            // Link
            if (parts.ContainsKey((int)AuctioneerItemIndex.Link)) {
                link = parts[(int)AuctioneerItemIndex.Link];
            } else {
                link = String.Empty;
            }

            // Item Level
            if (parts.ContainsKey((int)AuctioneerItemIndex.ItemLevel)) {
                item_level = int.Parse(parts[(int)AuctioneerItemIndex.ItemLevel]);
            } else {
                item_level = 0;
            }

            // Type
            if (parts.ContainsKey((int)AuctioneerItemIndex.Type)) {
                type = parts[(int)AuctioneerItemIndex.Type];
            } else {
                type = String.Empty;
            }

            // Sub-Type
            if (parts.ContainsKey((int)AuctioneerItemIndex.SubType)) {
                sub_type = parts[(int)AuctioneerItemIndex.SubType];
            } else {
                sub_type = String.Empty;
            }

            // Equipment Slot
            if (parts.ContainsKey((int)AuctioneerItemIndex.EquipmentSlot)) {
                equip_slot = (AuctioneerEquipmentSlot)int.Parse(parts[(int)AuctioneerItemIndex.EquipmentSlot]);
            } else {
                equip_slot = AuctioneerEquipmentSlot.None;
            }

            // Price
            if (parts.ContainsKey((int)AuctioneerItemIndex.Price)) {
                price = new AuctioneerMoney(int.Parse(parts[(int)AuctioneerItemIndex.Price]));
            } else {
                price = new AuctioneerMoney(0);
            }

            // Time Left
            if (parts.ContainsKey((int)AuctioneerItemIndex.TimeLeft)) {
                time_left = (AuctioneerTimeLeft)int.Parse(parts[(int)AuctioneerItemIndex.TimeLeft]);
            } else {
                time_left = AuctioneerTimeLeft.Unknown;
            }

            // Time
            if (parts.ContainsKey((int)AuctioneerItemIndex.Time)) {
                long value = long.Parse(parts[(int)AuctioneerItemIndex.Time]);

                time = DateUtils.UnixToDateTime(value);
            } else {
                time = DateUtils.UnixEpoch;
            }

            // Name
            if (parts.ContainsKey((int)AuctioneerItemIndex.Name)) {
                name = parts[(int)AuctioneerItemIndex.Name];
            } else {
                name = String.Empty;
            }

            // Texture
            if (parts.ContainsKey((int)AuctioneerItemIndex.Texture)) {
                texture = parts[(int)AuctioneerItemIndex.Texture];
            } else {
                texture = String.Empty;
            }

            // Stack Count
            if (parts.ContainsKey((int)AuctioneerItemIndex.Count)) {
                count = int.Parse(parts[(int)AuctioneerItemIndex.Count]);
            } else {
                count = 0;
            }

            // Quality
            if (parts.ContainsKey((int)AuctioneerItemIndex.Quality)) {
                quality = (AuctioneerItemQuality)int.Parse(parts[(int)AuctioneerItemIndex.Quality]);
            } else {
                quality = AuctioneerItemQuality.Unknown;
            }

            // Can Use
            if (parts.ContainsKey((int)AuctioneerItemIndex.CanUse)) {
                can_use = int.Parse(parts[(int)AuctioneerItemIndex.CanUse]);
            } else {
                can_use = 0;
            }

            // Usable Level
            if (parts.ContainsKey((int)AuctioneerItemIndex.UsableLevel)) {
                usable_level = int.Parse(parts[(int)AuctioneerItemIndex.UsableLevel]);
            } else {
                usable_level = 0;
            }

            // Minimum Bid
            if (parts.ContainsKey((int)AuctioneerItemIndex.MinBid)) {
                min_bid = new AuctioneerMoney(int.Parse(parts[(int)AuctioneerItemIndex.MinBid]));
            } else {
                min_bid = AuctioneerMoney.Empty;
            }

            // Minimum Increment
            if (parts.ContainsKey((int)AuctioneerItemIndex.MinIncrement)) {
                min_inc = new AuctioneerMoney(int.Parse(parts[(int)AuctioneerItemIndex.MinIncrement]));
            } else {
                min_inc = AuctioneerMoney.Empty;
            }

            // Buyout
            if (parts.ContainsKey((int)AuctioneerItemIndex.BuyOut)) {
                buy_out = new AuctioneerMoney(int.Parse(parts[(int)AuctioneerItemIndex.BuyOut]));
            } else {
                buy_out = AuctioneerMoney.Empty;
            }

            // Current Bid
            if (parts.ContainsKey((int)AuctioneerItemIndex.CurrentBid)) {
                cur_bid = new AuctioneerMoney(int.Parse(parts[(int)AuctioneerItemIndex.CurrentBid]));
            } else {
                cur_bid = AuctioneerMoney.Empty;
            }

            // Am High
            if (parts.ContainsKey((int)AuctioneerItemIndex.AmHigh)) {
                am_high = bool.Parse(parts[(int)AuctioneerItemIndex.AmHigh]);
            } else {
                am_high = false;
            }

            // Seller
            if (parts.ContainsKey((int)AuctioneerItemIndex.Seller)) {
                seller = parts[(int)AuctioneerItemIndex.Seller];
            } else {
                seller = String.Empty;
            }

            // Flag
            if (parts.ContainsKey((int)AuctioneerItemIndex.Flag)) {
                flag = (AuctioneerItemFlag)int.Parse(parts[(int)AuctioneerItemIndex.Flag]);
            } else {
                flag = AuctioneerItemFlag.Unknown;
            }

            // Auctioneer ID
            if (parts.ContainsKey((int)AuctioneerItemIndex.AuctioneerId)) {
                auctioneer_id = int.Parse(parts[(int)AuctioneerItemIndex.AuctioneerId]);
            } else {
                auctioneer_id = 0;
            }

            // Item ID
            if (parts.ContainsKey((int)AuctioneerItemIndex.ItemId)) {
                item_id = int.Parse(parts[(int)AuctioneerItemIndex.ItemId]);
            } else {
                item_id = 0;
            }

            // Suffix
            if (parts.ContainsKey((int)AuctioneerItemIndex.Suffix)) {
                suffix = int.Parse(parts[(int)AuctioneerItemIndex.Suffix]);
            } else {
                suffix = 0;
            }

            // Factor
            if (parts.ContainsKey((int)AuctioneerItemIndex.Factor)) {
                factor = int.Parse(parts[(int)AuctioneerItemIndex.Factor]);
            } else {
                factor = 0;
            }

            // Enchant
            if (parts.ContainsKey((int)AuctioneerItemIndex.Enchant)) {
                enchant = int.Parse(parts[(int)AuctioneerItemIndex.Enchant]);
            } else {
                enchant = 0;
            }

            // Seed
            if (parts.ContainsKey((int)AuctioneerItemIndex.Seed)) {
                seed = long.Parse(parts[(int)AuctioneerItemIndex.Seed]);
            } else {
                seed = 0;
            }
        }

        #region Methods

        private string GetPart(List<string> parts, string defualtValue, string itemType, string itemSubType, AuctioneerItemIndex itemIndex)
        {
            //try {
                string path = "Codeology.Auctioneer.IndexMappings.xml";
                Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(path);
                XmlDocument xml = new XmlDocument();

                xml.Load(stream);

                XmlNode index_node = xml.SelectSingleNode(String.Format("/IndexMappings/IndexMap[@name='{0}']/Scope[@name='{1}']/Index[@name='{2}']",itemType,itemSubType,itemIndex.ToString()));

                if (index_node == null) throw new Exception(String.Format("Could not find index map for {0}:{1}.",itemType,itemSubType));

            try {
                int idx = int.Parse(index_node.Attributes["index"].Value);

                return parts[idx];
            } catch {
                return defualtValue;
            }
        }

        #endregion

        #region Properties

        public string Link
        {
            get {
                return link;
            }
        }

        public int ItemLevel
        {
            get {
                return item_level;
            }
        }

        public string Type
        {
            get {
                return type;
            }
        }

        public string SubType
        {
            get {
                return sub_type;
            }
        }

        public AuctioneerEquipmentSlot EquipmentSlot
        {
            get {
                return equip_slot;
            }
        }

        public AuctioneerMoney Price
        {
            get {
                return price;
            }
        }

        public AuctioneerTimeLeft TimeLeft
        {
            get {
                return time_left;
            }
        }

        public DateTime Time
        {
            get {
                return time;
            }
        }

        public string Name
        {
            get {
                return name;
            }
        }

        public string Texture
        {
            get {
                return texture;
            }
        }

        public int StackCount
        {
            get {
                return count;
            }
        }

        public AuctioneerItemQuality Quality
        {
            get {
                return quality;
            }
        }

        public int CanUse
        {
            get {
                return can_use;
            }
        }

        public int UsableLevel
        {
            get {
                return usable_level;
            }
        }

        public AuctioneerMoney MinimumBid
        {
            get {
                return min_bid;
            }
        }

        public AuctioneerMoney MinimumInc
        {
            get {
                return min_inc;
            }
        }

        public AuctioneerMoney Buyout
        {
            get {
                return buy_out;
            }
        }

        public AuctioneerMoney CurrentBid
        {
            get {
                return cur_bid;
            }
        }

        public bool AmHigh
        {
            get {
                return am_high;
            }
        }

        public string Seller
        {
            get {
                return seller;
            }
        }

        public AuctioneerItemFlag Flag
        {
            get {
                return flag;
            }
        }

        public int AuctioneerId
        {
            get {
                return auctioneer_id;
            }
        }

        public int ItemId
        {
            get {
                return item_id;
            }
        }

        public int Suffix
        {
            get {
                return suffix;
            }
        }

        public int Factor
        {
            get {
                return factor;
            }
        }

        public int Enchant
        {
            get {
                return enchant;
            }
        }

        public long Seed
        {
            get {
                return seed;
            }
        }

        #endregion

    }

}
